﻿using Infrastructure.DomainEvent;
using Infrastructure.MessageBus;
using MassTransit;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Domain
{
    public class EventDispatcher : IEventDispatcher
    {
        public IBus bus { get; set; }
        public async Task DispatchAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = default) where TEntity : EntityEntry
        {
            var aggregateRoot = entity.Entity as Infrastructure.AggregateBase.AggregateRoot;

            if (aggregateRoot == null) return;

            var events = aggregateRoot.GetDomainEvents();

            if (events != null && events.Count > 0)
            {
                foreach (var item in events)
                {
                    var queue = MessageBusQueueNameUtils.GetQueueName(item.GetType().Name);
                    var endpoint = await bus.GetSendEndpoint(queue.Item2);
                    await endpoint.Send(item, item.GetType(), cancellationToken);
                }
            }

            var adminEvents = aggregateRoot.GetAdminDomainEvents();
            if (adminEvents != null && adminEvents.Count > 0)
            {
                foreach (var item in adminEvents)
                {
                    var adminQueue = MessageBusAdminQueueNameUtils.GetQueueName(item.GetType().Name);
                    var endpoint = await bus.GetSendEndpoint(adminQueue.Item2);
                    await endpoint.Send(item, item.GetType(), cancellationToken);
                }
            }
        }

        public async Task SendApiEvent(DomainEventBase domainEventBase, CancellationToken cancellationToken = default)
        {
            var queue = MessageBusQueueNameUtils.GetQueueName(domainEventBase.GetType().Name);
            var endpoint = await bus.GetSendEndpoint(queue.Item2);
            await endpoint.Send(domainEventBase, domainEventBase.GetType(), cancellationToken);
        }

        public async Task DispatchEntitysAsync<TEntity>(List<TEntity> aggregateRoots, CancellationToken cancellationToken = default) where TEntity : EntityEntry
        {
            foreach (var item in aggregateRoots)
            {
                await DispatchAsync(item);
            }
        }

        //public async Task DispatchEventAsync<TDomainEvent>(TDomainEvent domainEvent, CancellationToken cancellationToken = default) where TDomainEvent : IDomainEvent
        //{
        //    var endpoint = await bus.GetSendEndpoint("GoLife.UV");

        //    await endpoint.Send(domainEvent, domainEvent.GetType(), cancellationToken);
        //}
    }
}
